package org.whatever.aha.zjut.platform.service.project;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.whatever.aha.zjut.base.constant.ErrorCode;
import org.whatever.aha.zjut.base.exception.AppException;
import org.whatever.aha.zjut.platform.dto.project.ProjectMemberDto;
import org.whatever.aha.zjut.platform.entity.competition.Competition;
import org.whatever.aha.zjut.platform.entity.competition.CompetitionStaticTags;
import org.whatever.aha.zjut.platform.entity.project.Project;
import org.whatever.aha.zjut.platform.entity.project.ProjectMember;
import org.whatever.aha.zjut.platform.mapper.StudentInfoMapper;
import org.whatever.aha.zjut.platform.mapper.competition.CompetitionMapper;
import org.whatever.aha.zjut.platform.mapper.project.ProjectMapper;
import org.whatever.aha.zjut.platform.mapper.project.ProjectMemberMapper;
import org.whatever.aha.zjut.platform.vo.StudentInfoVo;
import org.whatever.aha.zjut.platform.vo.project.ProjectMemberDetailVo;
import org.whatever.aha.zjut.platform.vo.project.ProjectMemberVo;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author Vc
 * @version 1.0
 * @Desc
 * @date 2021/09/15 0:03
 */
@RequiredArgsConstructor
@Service
public class ProjectMemberService {
    final ProjectMemberMapper projectMemberMapper;
    final StudentInfoMapper studentInfoMapper;
    final CompetitionMapper competitionMapper;
    final ProjectMapper projectMapper;

    /**
     * 根据项目成员ID添加项目成员
     *
     * @param userId 项目成员ID
     */
    @Transactional(rollbackFor = Exception.class, propagation= Propagation.REQUIRED)
    public String addProjectMemberByProjectId(int userId, int projectId, int rank, String job) {
        ProjectMember projectMember = new ProjectMember(projectId, userId, rank, job);
        return "" + projectMemberMapper.insert(projectMember);
    }


    /**
     * 根据项目id和用户id删除项目成员
     *
     * @param projectId 项目id
     * @param userId    用户id
     */
    @Transactional(rollbackFor = Exception.class, propagation= Propagation.REQUIRED)
    public int deleteProjectMember(int projectId, Integer userId) {
        if(userId != null && projectMemberMapper.selectCount(new QueryWrapper<ProjectMember>().eq("project_id",projectId).eq("member_id",userId))<1){
            throw new AppException(ErrorCode.PROJECT_MEMBER_LACK);
        }
        return projectMemberMapper.delete(new QueryWrapper<ProjectMember>().eq("project_id",projectId).eq(userId != null, "member_id", userId));
    }

    /**
     * 根据项目id更新项目成员
     *
     * @param projectMemberDto 更新的项目成员
     */
    @Transactional(rollbackFor = Exception.class, propagation= Propagation.REQUIRED)
    public int  updateProjectMember(ProjectMemberDto projectMemberDto, int projectId) {
        if(projectMemberMapper.selectCount(new QueryWrapper<ProjectMember>().eq("project_id",projectId))<1){
            throw new AppException(ErrorCode.PROJECT_MEMBER_LACK);
        }
        ProjectMember projectMember = new ProjectMember();
        BeanUtils.copyProperties(projectMemberDto, projectMember);
        projectMember.setProjectId(projectId);
        return projectMemberMapper.update(projectMember, new QueryWrapper<ProjectMember>().eq("project_id",projectMember.getProjectId()).eq("member_id",projectMember.getMemberId()));
    }

    /**
     * 批量更新项目成员
     *
     * @param projectMemberDtos 更新的项目多个成员
     * @param projectId      项目id
     */
    @Transactional(rollbackFor = {Exception.class}, propagation= Propagation.REQUIRED)
    public String updateProjectMembers(List<ProjectMemberDto> projectMemberDtos, int projectId) {
        if(projectMemberMapper.selectCount(new QueryWrapper<ProjectMember>().eq("project_id",projectId))<1){
            throw new AppException(ErrorCode.PROJECT_MEMBER_LACK);
        }
        int accumulate = 0;
        // 删除所有非队长角色
        projectMemberMapper.delete(new QueryWrapper<ProjectMember>().eq("project_id",projectId).ne("project_member_rank",1));
        // 插入批量信息
        for (ProjectMemberDto projectMemberDto : projectMemberDtos) {
            ProjectMember projectMember = new ProjectMember();
            BeanUtils.copyProperties(projectMemberDto, projectMember);
            projectMember.setProjectId(projectId);
            accumulate += projectMemberMapper.insert(projectMember);
        }
        return "批量更新"+ accumulate +"条记录成功！";
    }

    /**
     * 根据userId获得user信息
     */
    public ProjectMemberVo getProjectMemberVoById(int userId, int projectId){
        return projectMemberMapper.getProjectMemberVoById(userId, projectId);
    }

    /**
     * 查询得到当前项目的最低排位
     */
    public int getRank(int projectId){
        List<Object> existRankList = projectMemberMapper.selectObjs(new QueryWrapper<ProjectMember>().eq("project_id", projectId).orderByAsc("project_member_rank").select("project_member_rank"));
        //双指针法获得当前最小的排位
        int idx1 = 0,idx2 =0;
        int memberLimit = (int) competitionMapper.selectObjs(new QueryWrapper<Competition>().eq("comp_id",this.getCompIdByProjectId(projectId)).select("team_num")).get(0);
        while(idx1 < memberLimit && idx2 < existRankList.size()){
            if(idx1+1 == (int) existRankList.get(idx2)){
                idx1++;idx2++;
            }else{
                //可以直接返回idx1 + 1
                return Math.min(idx1,idx2) + 1;
            }
        }
        //可以直接返回0
        return idx1 == memberLimit ? 0 : idx1;
    }

    /**
     * 查询得到当前项目Id对应的竞赛Id
     */
    public Object getCompIdByProjectId (int projectId){
        return projectMapper.selectObjs(new QueryWrapper<Project>().eq("project_id",projectId).select("comp_id")).get(0);
    }

    /**
     * 根据userId获得user信息
     */
    public StudentInfoVo getStudentInfoVoById(int userId){
        return studentInfoMapper.getStudentInfoVoById(userId);
    }

    /**
     * 获取当前项目所有userId列表
     */
    public List<Object> getUserIdList(int projectId){
        return projectMemberMapper.selectObjs(new QueryWrapper<ProjectMember>().eq("project_id",projectId).select("member_id"));
    }


    /**
     * 获得当前项目所有详细成员信息（包含个人学号等）
     */
    public List<ProjectMemberDetailVo> getMemberDetail(int projectId){
        List<Object> userList = this.getUserIdList(projectId);
        List<ProjectMemberDetailVo> projectMemberDetailVos = new ArrayList<ProjectMemberDetailVo>();
        userList.forEach(
                userId ->{
                    ProjectMemberDetailVo projectMemberDetailVo = new ProjectMemberDetailVo();
                    projectMemberDetailVo.setProjectMemberVo(this.getProjectMemberVoById((int) userId, projectId));
                    projectMemberDetailVo.setStudentInfoVo(this.getStudentInfoVoById((int) userId));
                    projectMemberDetailVos.add(projectMemberDetailVo);
                }
        );
        return projectMemberDetailVos;
    }

    /**
     * 获得当前项目所有粗略成员信息（只包含团队信息）
     */
    public List<ProjectMemberVo> getMemberRough(int projectId){
        List<Object> userList = this.getUserIdList(projectId);
        List<ProjectMemberVo> projectMemberVoList = new ArrayList<ProjectMemberVo>();
        userList.forEach(
                userId ->{
                    projectMemberVoList.add(this.getProjectMemberVoById((int) userId, projectId));
                }
        );
        return projectMemberVoList;
    }

    /**
     * 获得已存在的rankList，排除修改人
     *
     * @param projectId
     * @return
     */
    public List<Object> getRankList(int projectId, int userId){
        return projectMemberMapper.selectObjs(new QueryWrapper<ProjectMember>().eq("project_id",projectId).ne("member_id",userId).select("project_member_rank"));
    }

    /**
     * 获得某用户参与的所有竞赛Id
     *
     * @param memberId
     * @return
     */
    public Set<Integer> getProjectIdByMemberIdConditional(int memberId, Integer compType, Integer compStatus, Integer compYear){
        return  projectMemberMapper.getProjectIdByMemberIdConditional(memberId, compType, compStatus, compYear);
    }
}
